Skip to content

OLS-2722: olsToolUIs initial support#1576

Open
iNecas wants to merge 2 commits intoopenshift:mainfrom
iNecas:ols-tool-ui
Open

OLS-2722: olsToolUIs initial support#1576
iNecas wants to merge 2 commits intoopenshift:mainfrom
iNecas:ols-tool-ui

Conversation

@iNecas
Copy link
Copy Markdown

@iNecas iNecas commented Mar 2, 2026

Allows plugins to define 'ols.tool-ui' extensions to map the tools to react components to be rendered when the tool gets called.

Sample extensions registration:

{
  "type": "ols.tool-ui",
  "properties": {
    "id": "my-obs/my-tool",
    "component": {
      "$codeRef": "MyToolUI"
    }
  }
}

The ToolUI implemntation receives the tool details in it's argument:

type MyTool = {
  name: 'my-tool';
  args: object,
  // ...
};

export const MyToolUI React.FC<{ tool: MyTool }> = ({ tool }) => {
  // component implementation
}

Depends on openshift/lightspeed-service#2779

This allows monitoring-plugin to define a UI for obs-mcp tools
image

Related changes leveraging this feature:

@iNecas iNecas marked this pull request as draft March 2, 2026 15:40
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 2, 2026
@openshift-ci openshift-ci bot requested review from syedriko and xrajesh March 2, 2026 15:41
@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 2, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign xrajesh for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@iNecas iNecas changed the title olsToolUIs initial support OLS-2722: olsToolUIs initial support Mar 6, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 6, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 6, 2026

@iNecas: This pull request references OLS-2722 which is a valid jira issue.

Details

In response to this:

Allows plugins to define 'ols.tool-ui' extensions to map the tools to react components to be rendered when the tool gets called.

Sample extensions registration:

{
 "type": "ols.tool-ui",
 "properties": {
   "id": "my-obs/my-tool",
   "component": {
     "$codeRef": "MyToolUI"
   }
 }
}

The ToolUI implemntation receives the tool details in it's argument:

type MyTool = {
 name: 'my-tool';
 args: object,
 // ...
};

export const MyToolUI React.FC<{ tool: MyTool }> = ({ tool }) => {
 // component implementation
}

Depends on openshift/lightspeed-service#2779

This allows monitoring-plugin to define a UI for obs-mcp tools
image

Related changes leveraging this feature:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link
Copy Markdown
Member

@kyoto kyoto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @iNecas. Thanks!

Just 2 minor comments and could you please run npm run lint-fix to address the lint errors and rebase?

import type { OlsToolUIComponent } from '../types';

type ToolUIExtensionProperties = {
/** Id of the component (as refferrenced by the mcp tool) */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Id of the component (as refferrenced by the mcp tool) */
/** ID of the component (as referenced by the MCP tool) */

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +13 to +16
export const OlsToolUI: React.FC<OlsToolUIProps> = ({ tool, toolUIComponent: toolUIElement }) => {
const ToolComponent = toolUIElement;
return <ToolComponent tool={tool} />;
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const OlsToolUI: React.FC<OlsToolUIProps> = ({ tool, toolUIComponent: toolUIElement }) => {
const ToolComponent = toolUIElement;
return <ToolComponent tool={tool} />;
};
export const OlsToolUI: React.FC<OlsToolUIProps> = ({ tool, toolUIComponent: ToolComponent }) => {
return <ToolComponent tool={tool} />;
};

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, done

@kyoto
Copy link
Copy Markdown
Member

kyoto commented Mar 17, 2026

Also, we should add a brief description of how to use this extension to the README

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 17, 2026
@openshift-merge-robot
Copy link
Copy Markdown

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

Walkthrough

Adds runtime support for rendering external plugin-provided tool UI components: new hook to map plugin extensions, new components to render mapped UIs per chat entry, a small event-payload change to propagate the UI id, and corresponding type updates and docs.

Changes

Cohort / File(s) Summary
Tool UI components
src/components/OlsToolUIs.tsx
Adds OlsToolUI (wraps a tool UI component in an ErrorBoundary) and OlsToolUIs (reads tools for an entry, resolves UI components via mapping, filters errored/missing, renders list). Exports default OlsToolUIs.
Hook: tool UI mapping
src/hooks/useToolUIMapping.ts
Adds useToolUIExtensions and useToolUIMapping to resolve ols.tool-ui extensions and return a memoized id→component mapping plus resolution boolean.
Type updates
src/types.ts
Adds exported OlsToolUIComponent = React.ComponentType<{ tool: Tool }>; changes Tool.args from { [k: string]: Array<string> } to { [k: string]: string }; adds required olsToolUiID: string to Tool.
Event payload propagation
src/components/Prompt.tsx
When handling tool_result stream events, extracts toolMeta?.olsUi?.id and includes it as olsToolUiID in the chatHistoryUpdateTool dispatch payload when present.
Render integration
src/components/ResponseTools.tsx
Imports and renders <OlsToolUIs entryIndex={entryIndex} /> alongside existing tool UI (MCPApp) and label rendering.
Documentation
README.md
Adds a section describing how external plugins provide tool visualization via _meta.additionalFields.olsUi.id and an ols.tool-ui extension mapping id→component.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 26, 2026
@iNecas
Copy link
Copy Markdown
Author

iNecas commented Mar 26, 2026

I've rebased and fixed an issue where we were visualizing the tool calls in failed state as well.

I will proceed with final cleanup and will switch to non-draft state for final review after that.

@kyoto
Copy link
Copy Markdown
Member

kyoto commented Mar 26, 2026

@iNecas Probably also a good idea to wrap the OlsToolUIs in an <ErrorBoundary>

@openshift-ci openshift-ci bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 27, 2026
@iNecas iNecas marked this pull request as ready for review March 27, 2026 16:57
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 27, 2026
Allows plugins to define 'ols.tool-ui' extensions to map the tools
to react components to be rendered when the tool gets called.

Sample extensions registration:

```json
{
  "type": "ols.tool-ui",
  "properties": {
    "id": "my-obs/my-tool",
    "component": {
      "$codeRef": "MyToolUI"
    }
  }
}
```

The ToolUI implemntation receives the tool details in it's argument:

```ts
type MyTool = {
  name: 'my-tool';
  args: object,
  // ...
};

export const MyToolUI React.FC<{ tool: MyTool }> = ({ tool }) => {
  // component implementation
}
```
@openshift-ci openshift-ci bot requested review from joshuawilson and kyoto March 27, 2026 16:58
@openshift-ci openshift-ci bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 27, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/OlsToolUIs.tsx`:
- Around line 27-37: toolsData can be undefined causing olsToolsWithUI to throw
when calling .map(); guard by converting undefined to an empty Immutable Map or
early-return before mapping: in the selector call/assignment for toolsData
(where useSelector retrieves s.plugins?.ols?.getIn(['chatHistory', entryIndex,
'tools'])), ensure toolsData is set to an empty Immutable.Map() when falsy, or
check toolsData before creating olsToolsWithUI; then run .map()/.filter only on
a guaranteed Immutable collection so olsToolsWithUI, toolUIMapping, and
downstream code using tool and toolUIComponent are safe.

In `@src/types.ts`:
- Line 38: The olsToolUiID property in the type definition is currently required
but is treated as optional in usage (see olsToolUiID references in Prompt.tsx
and OlsToolUIs.tsx and the fact it may arrive only with tool_result events), so
update the type that declares olsToolUiID to make it optional (e.g., change
olsToolUiID: string to olsToolUiID?: string) so the compiler reflects actual
runtime behavior and avoids false positives in places that guard against its
absence; ensure you update the interface or type in src/types.ts where
olsToolUiID is declared and run type checks to verify callers (Prompt.tsx,
OlsToolUIs.tsx, any tool_call/tool_result handlers) still compile.
- Line 31: The args field in the shared type is declared as "{ [key: string]:
string }" but the codebase uses it as a generic map (ResponseToolModal.tsx casts
to Record<string, unknown> and MCPApp.tsx's handleToolCall expects
Record<string, unknown>). Update the type definition for args to Record<string,
unknown> in the declaration (the symbol to change is the args field in the type
in src/types.ts) so it matches the actual usage and avoids unsafe casts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 373c36eb-a1a5-4c6e-8c57-072ed2d2d095

📥 Commits

Reviewing files that changed from the base of the PR and between 9bd153f and 39e1e73.

📒 Files selected for processing (5)
  • src/components/OlsToolUIs.tsx
  • src/components/Prompt.tsx
  • src/components/ResponseTools.tsx
  • src/hooks/useToolUIMapping.ts
  • src/types.ts

Comment on lines +27 to +37
const toolsData: ImmutableMap<string, ImmutableMap<string, unknown>> = useSelector((s: State) =>
s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
);

const olsToolsWithUI = toolsData
.map((value) => {
const tool = value.toJS() as Tool;
const toolUIComponent = tool.olsToolUiID && toolUIMapping[tool.olsToolUiID];
return { tool, toolUIComponent };
})
.filter(({ tool, toolUIComponent }) => tool.status !== 'error' && !!toolUIComponent);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add null guard for toolsData to prevent runtime errors.

If entryIndex is invalid or the chat entry doesn't have tools yet, getIn returns undefined. Calling .map() on undefined will throw a runtime error.

Proposed fix
   const toolsData: ImmutableMap<string, ImmutableMap<string, unknown>> = useSelector((s: State) =>
     s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
   );
 
+  if (!toolsData) {
+    return null;
+  }
+
   const olsToolsWithUI = toolsData
     .map((value) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const toolsData: ImmutableMap<string, ImmutableMap<string, unknown>> = useSelector((s: State) =>
s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
);
const olsToolsWithUI = toolsData
.map((value) => {
const tool = value.toJS() as Tool;
const toolUIComponent = tool.olsToolUiID && toolUIMapping[tool.olsToolUiID];
return { tool, toolUIComponent };
})
.filter(({ tool, toolUIComponent }) => tool.status !== 'error' && !!toolUIComponent);
const toolsData: ImmutableMap<string, ImmutableMap<string, unknown>> = useSelector((s: State) =>
s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
);
if (!toolsData) {
return null;
}
const olsToolsWithUI = toolsData
.map((value) => {
const tool = value.toJS() as Tool;
const toolUIComponent = tool.olsToolUiID && toolUIMapping[tool.olsToolUiID];
return { tool, toolUIComponent };
})
.filter(({ tool, toolUIComponent }) => tool.status !== 'error' && !!toolUIComponent);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/OlsToolUIs.tsx` around lines 27 - 37, toolsData can be
undefined causing olsToolsWithUI to throw when calling .map(); guard by
converting undefined to an empty Immutable Map or early-return before mapping:
in the selector call/assignment for toolsData (where useSelector retrieves
s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools'])), ensure toolsData
is set to an empty Immutable.Map() when falsy, or check toolsData before
creating olsToolsWithUI; then run .map()/.filter only on a guaranteed Immutable
collection so olsToolsWithUI, toolUIMapping, and downstream code using tool and
toolUIComponent are safe.


export type Tool = {
args: { [key: string]: Array<string> };
args: { [key: string]: string };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for existing usages of tool.args to verify the expected structure
rg -n "tool\.args|args\[" --type=ts -C3

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

cat -n src/types.ts | head -50

Repository: openshift/lightspeed-console

Length of output: 1392


🏁 Script executed:

rg -n "args" src/types.ts -B2 -A2

Repository: openshift/lightspeed-console

Length of output: 178


🏁 Script executed:

# Search more broadly for how args is used in the codebase
rg "\.args" --type=ts -i | head -20

Repository: openshift/lightspeed-console

Length of output: 529


🏁 Script executed:

# Search for API response examples or test data that might show the actual structure
fd -e "test\|spec\|mock" -t f | head -10

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

# Search for Tool type usage
rg "tool\.args|Tool\>" --type=ts -A2 -B2 | head -40

Repository: openshift/lightspeed-console

Length of output: 170


🏁 Script executed:

# Look for streaming or API-related code
fd -e ts -e tsx | xargs rg "stream|api|tool_call" -l | head -10

Repository: openshift/lightspeed-console

Length of output: 319


🏁 Script executed:

# Check git history to see what the type changed from
git log --oneline -p src/types.ts | head -100

Repository: openshift/lightspeed-console

Length of output: 1818


🏁 Script executed:

rg "tool\.args" src/components/ -B3 -A3

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

rg "args" src/attachments.ts -B2 -A2

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

# Check if Tool type existed in a different location before
git log --all --full-history -S "type Tool" --oneline

Repository: openshift/lightspeed-console

Length of output: 158


🏁 Script executed:

cat src/components/Prompt.tsx | grep -n "tool" -i -C3 | head -50

Repository: openshift/lightspeed-console

Length of output: 1415


🏁 Script executed:

cat src/components/AttachEventsModal.tsx | grep -n "tool\|args" -i -C2 | head -40

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

# Search for any access to Tool properties
rg "tool\[|tool\." src/ --type=ts --type=tsx -C2

Repository: openshift/lightspeed-console

Length of output: 99


🏁 Script executed:

rg "tool\[|tool\." src/ -C2 | head -80

Repository: openshift/lightspeed-console

Length of output: 1975


🏁 Script executed:

# Check what the review is referring to - search for Array<string> type references
rg "Array<string>" src/types.ts

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

# Look at the full context of how Tool type is used in components
fd -e ts -e tsx -path "*/src/components/*" | xargs cat | grep -A5 -B5 "Tool"

Repository: openshift/lightspeed-console

Length of output: 240


🏁 Script executed:

# Check if there's any documentation or API reference
fd -e md | xargs cat | grep -i "args\|tool" | head -20

Repository: openshift/lightspeed-console

Length of output: 54


🏁 Script executed:

rg "args.*Record|args.*unknown" src/ -B2 -A2

Repository: openshift/lightspeed-console

Length of output: 811


🏁 Script executed:

# Check all Tool property usages to see if args is accessed directly anywhere
rg "\.args\[|\.args\." src/ -C3

Repository: openshift/lightspeed-console

Length of output: 54


Fix args type to match actual usage patterns.

The args field type is defined as { [key: string]: string }, but the codebase expects it to hold values of any type. In ResponseToolModal.tsx, the code casts args as Record<string, unknown>, and in MCPApp.tsx, handleToolCall expects args: Record<string, unknown>. The type definition should be changed to Record<string, unknown> to reflect the actual API contract and prevent type safety issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/types.ts` at line 31, The args field in the shared type is declared as "{
[key: string]: string }" but the codebase uses it as a generic map
(ResponseToolModal.tsx casts to Record<string, unknown> and MCPApp.tsx's
handleToolCall expects Record<string, unknown>). Update the type definition for
args to Record<string, unknown> in the declaration (the symbol to change is the
args field in the type in src/types.ts) so it matches the actual usage and
avoids unsafe casts.

uiResourceUri?: string;
serverName?: string;
structuredContent?: Record<string, unknown>;
olsToolUiID: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

olsToolUiID should be optional to match actual usage.

The olsToolUiID field is defined as required, but the implementation shows it's conditionally populated:

  • In Prompt.tsx (line 634), it's only included when toolMeta?.olsUi?.id is present
  • In OlsToolUIs.tsx (line 34), there's a guard tool.olsToolUiID && toolUIMapping[...] suggesting it can be falsy
  • Tool entries are created incrementally via tool_call and tool_result events, where olsToolUiID only arrives with tool_result
Proposed fix
-  olsToolUiID: string;
+  olsToolUiID?: string;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
olsToolUiID: string;
olsToolUiID?: string;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/types.ts` at line 38, The olsToolUiID property in the type definition is
currently required but is treated as optional in usage (see olsToolUiID
references in Prompt.tsx and OlsToolUIs.tsx and the fact it may arrive only with
tool_result events), so update the type that declares olsToolUiID to make it
optional (e.g., change olsToolUiID: string to olsToolUiID?: string) so the
compiler reflects actual runtime behavior and avoids false positives in places
that guard against its absence; ensure you update the interface or type in
src/types.ts where olsToolUiID is declared and run type checks to verify callers
(Prompt.tsx, OlsToolUIs.tsx, any tool_call/tool_result handlers) still compile.

@iNecas
Copy link
Copy Markdown
Author

iNecas commented Mar 27, 2026

Addressed all review comments. Planning to finish the coderabbit ones + any other comments on Monday.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/components/OlsToolUIs.tsx (1)

27-31: ⚠️ Potential issue | 🔴 Critical

Guard toolsData before calling .map() to prevent a render crash.

At Line 31, .map() executes even when selector output is undefined (e.g., missing tools or invalid entryIndex), which throws at runtime.

Proposed fix
-  const toolsData: ImmutableMap<string, ImmutableMap<string, unknown>> = useSelector((s: State) =>
-    s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
-  );
+  const toolsData = useSelector(
+    (s: State): ImmutableMap<string, ImmutableMap<string, unknown>> | undefined =>
+      s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools']),
+  );
+
+  if (!toolsData) {
+    return null;
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/OlsToolUIs.tsx` around lines 27 - 31, toolsData (from the
useSelector that reads s.plugins?.ols?.getIn(['chatHistory', entryIndex,
'tools'])) can be undefined, and calling .map() on it when constructing
olsToolsWithUI causes a render crash; guard before mapping by checking toolsData
is defined (and is an Immutable Map/has size) and only call .map() when present,
otherwise set olsToolsWithUI to an empty array or Immutable List; update the
olsToolsWithUI assignment to conditionally map (e.g., if (toolsData) {
toolsData.map(...) } else fallback) so rendering is safe when entryIndex/tools
are missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 267-291: The README shows mismatched IDs between the MCP
annotation (_meta.additionalFields.olsUi.id set to 'my-mcp/my-tool') and the
plugin extension (the "ols.tool-ui" extension's properties.id set to
'my-obs/my-tool'); update one so both use the exact same tool UI id (e.g., make
both 'my-mcp/my-tool' or both 'my-obs/my-tool') so the mapping resolves; verify
the id in the annotation and the "ols.tool-ui" extension's properties.id match
exactly and keep the component.$codeRef (MyToolUI) unchanged.
- Around line 299-307: The example TypeScript component declaration is missing
the colon between the component name and its type annotation; update the
declaration for MyToolUI so the identifier MyToolUI is followed by a colon and
the React.FC type annotation (i.e., change the declaration with MyToolUI
React.FC<{ tool: MyTool }> to use a colon between MyToolUI and React.FC) so the
example compiles as valid TypeScript.

---

Duplicate comments:
In `@src/components/OlsToolUIs.tsx`:
- Around line 27-31: toolsData (from the useSelector that reads
s.plugins?.ols?.getIn(['chatHistory', entryIndex, 'tools'])) can be undefined,
and calling .map() on it when constructing olsToolsWithUI causes a render crash;
guard before mapping by checking toolsData is defined (and is an Immutable
Map/has size) and only call .map() when present, otherwise set olsToolsWithUI to
an empty array or Immutable List; update the olsToolsWithUI assignment to
conditionally map (e.g., if (toolsData) { toolsData.map(...) } else fallback) so
rendering is safe when entryIndex/tools are missing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4967151b-df62-49f6-a9e6-e8b1651b72bf

📥 Commits

Reviewing files that changed from the base of the PR and between 39e1e73 and 6d94fd0.

📒 Files selected for processing (3)
  • README.md
  • src/components/OlsToolUIs.tsx
  • src/hooks/useToolUIMapping.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/hooks/useToolUIMapping.ts

Comment on lines +267 to +291
1. annotate the particular MCP tool inside the MCP server:

``` json
_meta: {
additionalFields: {
olsUi: {
id: 'my-mcp/my-tool',
},
}
}
```

2. define an extension of type `ols.tool-ui` inside the plugin, connecting the tool (using the annotated id)
with the particular component:

``` json
{
"type": "ols.tool-ui",
"properties": {
"id": "my-obs/my-tool",
"component": {
"$codeRef": "MyToolUI"
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use the same tool UI id in both setup steps.

Line 273 (my-mcp/my-tool) and Line 286 (my-obs/my-tool) differ, but the mapping requires an exact id match. With this mismatch, the Tool UI will not resolve.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 267 - 291, The README shows mismatched IDs between
the MCP annotation (_meta.additionalFields.olsUi.id set to 'my-mcp/my-tool') and
the plugin extension (the "ols.tool-ui" extension's properties.id set to
'my-obs/my-tool'); update one so both use the exact same tool UI id (e.g., make
both 'my-mcp/my-tool' or both 'my-obs/my-tool') so the mapping resolves; verify
the id in the annotation and the "ols.tool-ui" extension's properties.id match
exactly and keep the component.$codeRef (MyToolUI) unchanged.

Comment on lines +299 to +307
``` typescript
type MyTool = {
name: 'my-tool';
args: object,
// ...
};

export const MyToolUI React.FC<{ tool: MyTool }> = ({ tool }) => {
// component implementation
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Expect 1 match before fix, 0 matches after fix
rg -n -C2 'export const MyToolUI React\.FC<\{ tool: MyTool \}>' README.md

Repository: openshift/lightspeed-console

Length of output: 194


Add missing colon in TypeScript component declaration.

Line 306 is missing the : between MyToolUI and React.FC, making the example invalid TypeScript that won't compile when copied.

Proposed fix
-export const MyToolUI React.FC<{ tool: MyTool }> = ({ tool }) => {
+export const MyToolUI: React.FC<{ tool: MyTool }> = ({ tool }) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 299 - 307, The example TypeScript component
declaration is missing the colon between the component name and its type
annotation; update the declaration for MyToolUI so the identifier MyToolUI is
followed by a colon and the React.FC type annotation (i.e., change the
declaration with MyToolUI React.FC<{ tool: MyTool }> to use a colon between
MyToolUI and React.FC) so the example compiles as valid TypeScript.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants